package es.uned.ii.si3.dao;

import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.apache.struts.util.LabelValueBean;
import es.uned.ii.si3.model.Alumno;
import es.uned.ii.si3.model.EstadosProyecto;
import es.uned.ii.si3.model.EstadosSolicitud;
import es.uned.ii.si3.model.Profesor;
import es.uned.ii.si3.model.Propuesta;
import es.uned.ii.si3.model.Proyecto;
import es.uned.ii.si3.model.Solicitud;
import es.uned.ii.si3.model.TipoPfc;

public class SolicitudDAOImpl implements SolicitudDAO {

	private static Logger log = Logger.getLogger(SolicitudDAOImpl.class);

		
	public SolicitudDAOImpl() {
		
	}
	
	public Long insert(Solicitud solicitud) throws SQLException {
			
		log.debug("SolicitudDAOImpl::insert Vamos a insertar la  siguiente solicitud: " + solicitud.toString());
		Connection conn = ConnectionFactory.getConnection();
		int idSolicitud = -1;
		PreparedStatement pstmt = null;
		ResultSet generatedKeys = null;
		try {
			pstmt = conn.prepareStatement("insert into solicitudes " +
					"(idAlumno,idPropuesta, urlDocumento, idEstado) " +
					" values (?,?,?, 1)");
			pstmt.setLong(1, solicitud.getAlumno().getIdUsuario());
			pstmt.setLong(2, solicitud.getPropuesta().getIdPropuesta());
			pstmt.setString(3, solicitud.getUrlDocumento());
			
			pstmt.executeUpdate();
			
			//generatedKeys = pstmt.getGeneratedKeys();
			generatedKeys = pstmt.executeQuery("SELECT LAST_INSERT_ID()");
			if ( generatedKeys.next() ) 
			{ 
				idSolicitud = generatedKeys.getInt(1); 
			}
			log.debug("SolicitudDAOImpl::insert. Hemos dado de alta la Solicitud con id: "+ idSolicitud);
		} catch (SQLException e) {
			e.printStackTrace();

		} finally {
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		
		if (idSolicitud == -1)
			throw new SQLException("Error insertando nueva solicitud");

		ConnectionFactory.release(conn);
		return new Long (idSolicitud);
	}

	public void loadByPrimaryKey(Solicitud solicitud) {
		// TODO Auto-generated method stub
		
	}
	
	public boolean update(Solicitud solicitud) {
		log.debug("SolicitudDAOImpl::update vamos actualizar la solicitud: " + solicitud.getIdSolicitud());
		Connection conn = ConnectionFactory.getConnection();
		PreparedStatement pstmt = null;
		boolean updateOK = true;

		try {
		pstmt = conn.prepareStatement("update solicitudes set " +
				" idAlumno =?, idPropuesta =? , urlDocumento = ?, idEstado = ? " +
				" where idRelacion= ?");
		
		
		pstmt.setInt(1, solicitud.getAlumno().getIdUsuario());
		pstmt.setInt(2, solicitud.getPropuesta().getIdPropuesta());
		pstmt.setString(3, solicitud.getUrlDocumento());
		pstmt.setInt(4, solicitud.getEstadoSolicitud().getIdEstado());
		pstmt.setInt(5, solicitud.getIdSolicitud());
			
		pstmt.executeUpdate();
		
		log.debug("SolicitudDAOImpl::update. Hemos actualizado la solicitud: "+ solicitud.getIdSolicitud());
		} catch (Exception e) {
			e.printStackTrace();
			updateOK = false;
		} finally {
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		
		ConnectionFactory.release(conn);
		return updateOK;

	}
	public Solicitud getSolicitudById(int idSolicitud){
			
		Connection conn = ConnectionFactory.getConnection();
		PreparedStatement pstmt = null;
		ResultSet resultado = null;
		Solicitud solicitud = null;
		try {
			log.debug("SolicitudesDAOImpl:Preparamos la consulta");
			pstmt = conn.prepareStatement("select sol.idRelacion as idSolicitud, us.idUsuario, us.dni, us.nombre, us.apellidos, sol.idPropuesta,"+
					"sol.urlDocumento,sol.idEstado, est.descripcion as estado, pro.idProfesor, pro.titulo, pro.anoAcademico,pro.idTipoPFC,pro.descripcion, pfc.descripcion as tipoPFC, "+
					"usp.idUsuario as idProfesor, usp.nombre as nombreProfesor, usp.apellidos as apellidosProfesor "+
					"from   usuarios us, solicitudes sol, propuestas pro, estados_solicitud est, tipo_pfc pfc, usuarios usp "+
					"where sol.idRelacion= ? "+ 
					"and usp.idUsuario=pro.idProfesor " +
					"and us.idUsuario=sol.idAlumno "+
					"and sol.idPropuesta=pro.idPropuesta "+					
					"and est.idEstado=sol.idEstado "+
					"and pfc.idTipoPFC=pro.idTipoPFC;");
			log.debug("SolicitudesDAOImpl:Pasamos a la consulta el numero de solicitud");
			pstmt.setInt(1, idSolicitud);
			resultado = pstmt.executeQuery();
			log.debug("SolicitudesDAOImpl:Consulta Ejecutada");
			if (resultado.next()){
				 Alumno alumno=new Alumno();
				 alumno.setIdUsuario(resultado.getInt("idUsuario"));
				 alumno.setNombre(resultado.getString("nombre"));
				 alumno.setApellidos(resultado.getString("apellidos"));
				 alumno.setDni(resultado.getString("dni"));
				    
				 TipoPfc tipoPFC=new TipoPfc();
				 tipoPFC.setIdTipoPfc(resultado.getInt("idTipoPFC"));
				 tipoPFC.setDescripcion(resultado.getString("tipoPFC"));
				    
				 Profesor profesor=new Profesor();
				 
				 profesor.setIdUsuario(resultado.getInt("idProfesor"));
				 profesor.setNombre(resultado.getString("nombreProfesor"));
				 profesor.setApellidos(resultado.getString("apellidosProfesor"));
				 
				 Propuesta propuesta=new Propuesta();
				 propuesta.setIdPropuesta(resultado.getInt("idPropuesta"));
				 propuesta.setTitulo(resultado.getString("titulo"));
				 propuesta.setTipoPfc(tipoPFC);
				 propuesta.setAnoAcademico(resultado.getInt("anoAcademico"));
				 propuesta.setDescripcion(resultado.getString("descripcion"));
				 propuesta.setProfesor(profesor);
				        
				 //Obtenemos el estado en que se encuentra la solicitud
				 EstadosSolicitud estado=new EstadosSolicitud();
				 estado.setIdEstado(resultado.getInt("idEstado"));
				 estado.setDescripcion(resultado.getString("estado"));
				    
				    			    
				 solicitud=new Solicitud(resultado.getInt("idSolicitud"),alumno,propuesta,estado,resultado.getString("urlDocumento"));
				 log.debug("SolicitudesDAOImpl:Solicitud Creada");
			}
		} catch (SQLException e) {
			solicitud = null;
		} finally {
			try {
				resultado.close();
				resultado = null;
			} catch (Exception e) { }
			
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		ConnectionFactory.release(conn);
		return solicitud;
	}
		
	public List getAllSolicitudesByAnyoAcademico(int anyoAcademico) throws SQLException{
		
		PreparedStatement pstmt = null;
		ResultSet resultado = null;
		ArrayList<Solicitud> listaSolicitudes=new ArrayList<Solicitud>();
		log.debug("SolicitudDAOImpl::getAllSolicitudesByYear Vamos a obtener todas las solicitudes por a�o academico: ");
		Connection conn = ConnectionFactory.getConnection();
		
		try{
			
			pstmt = conn.prepareStatement("select sol.idRelacion as idSolicitud, us.idUsuario, us.dni, us.nombre, us.apellidos, sol.idPropuesta," +
					" sol.urlDocumento,sol.idEstado, est.descripcion as estado, pro.titulo, pro.anoAcademico,pro.idTipoPFC, pfc.descripcion as tipoPFC " +
					" from   usuarios us, solicitudes sol, propuestas pro, estados_solicitud est, tipo_pfc pfc " +
					"where us.idUsuario=sol.idAlumno " +
					"and sol.idPropuesta=pro.idPropuesta " +
					"and pro.anoAcademico=?  " +
					"and est.idEstado=sol.idEstado " +
					"and pfc.idTipoPFC=pro.idTipoPFC");
			pstmt.setInt(1, anyoAcademico);
			
			resultado = pstmt.executeQuery();
			
			while (resultado.next()){
				
			
			    Alumno alumno=new Alumno();
			    alumno.setIdUsuario(resultado.getInt("idUsuario"));
			    alumno.setNombre(resultado.getString("nombre"));
			    alumno.setApellidos(resultado.getString("apellidos"));
			    alumno.setDni(resultado.getString("dni"));
			    
			    TipoPfc tipoPFC=new TipoPfc();
			    tipoPFC.setIdTipoPfc(resultado.getInt("idTipoPFC"));
			    tipoPFC.setDescripcion(resultado.getString("tipoPFC"));
			    
			    
			    Propuesta propuesta=new Propuesta();
			    propuesta.setIdPropuesta(resultado.getInt("idPropuesta"));
			    propuesta.setTitulo(resultado.getString("titulo"));
			    propuesta.setTipoPfc(tipoPFC);
			    propuesta.setAnoAcademico(resultado.getInt("anoAcademico"));
			        
			    //Obtenemos el estado en que se encuentra la solicitud
			    EstadosSolicitud estado=new EstadosSolicitud();
			    estado.setIdEstado(resultado.getInt("idEstado"));
			    estado.setDescripcion(resultado.getString("estado"));
			    
			    			    
			    Solicitud solicitud=new Solicitud(resultado.getInt("idSolicitud"),
			    								  alumno,propuesta,estado,resultado.getString("urlDocumento"));
				
			    //A�adimos la solicitud a la lista
			    listaSolicitudes.add(solicitud);
			}			
		}catch(SQLException e){
			log.error(e);
		} finally {
			try {
				resultado.close();
				resultado = null;
			} catch (Exception e) { }
			
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		
		ConnectionFactory.release(conn);
		return listaSolicitudes;
			
	}


	public List encuentraAnyosAcademicosDistintos() {
		
		/* Vamos a utilizar el mismo procedimiento almacenado que usamos para ver
		 * los a�os en las propuestas, ya que el a�o acad�mico de la solicitud
		 * debe ser el mismo que el de la propuesta
		 */
		log.debug("SolicitudDAOImpl::encuentraAnyosAcademicosDistintos obtenemos la lista de a�os academicos disponibles");
		Connection conn = ConnectionFactory.getConnection();
		PreparedStatement pstmt = null;
		ResultSet resultado = null;
		ArrayList<LabelValueBean> listaAnyos = new ArrayList<LabelValueBean>();
		try {
			pstmt = conn.prepareStatement("select distinct p.anoAcademico " +
					"from solicitudes s, propuestas p " +
					"where s.idPropuesta = p.idPropuesta");
		
			resultado = pstmt.executeQuery();
			while (resultado.next()){
				log.debug("encuentraAnyosAcademicosDistintos. A�adimos el a�o a la lista : " + resultado.getInt(1));
				listaAnyos.add(new LabelValueBean (resultado.getString(1), resultado.getString(1)));
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				resultado.close();
				resultado = null;
			} catch (Exception e) { }
			
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		
		ConnectionFactory.release(conn);
		return listaAnyos;
	}

	public List<Solicitud> getAllSolicitudes() throws SQLException {
				
		PreparedStatement pstmt = null;
		ResultSet resultado = null;
		ArrayList<Solicitud> listaSolicitudes=new ArrayList<Solicitud>();
		log.debug("SolicitudDAOImpl::getAllSolicitudes Vamos a obtener todas las solicitudes: ");
		Connection conn = ConnectionFactory.getConnection();
		
		try{
			pstmt = conn.prepareStatement("select sol.idRelacion as idSolicitud, us.idUsuario, us.dni, us.nombre, us.apellidos, sol.idPropuesta," +
					" sol.urlDocumento,sol.idEstado, est.descripcion as estado, pro.titulo, pro.anoAcademico,pro.idTipoPFC, pfc.descripcion as tipoPFC " +
					" from   usuarios us, solicitudes sol, propuestas pro, estados_solicitud est, tipo_pfc pfc " +
					" where us.idUsuario=sol.idAlumno " +
					"and sol.idPropuesta=pro.idPropuesta " +
					"and est.idEstado=sol.idEstado " +
					"and pfc.idTipoPFC=pro.idTipoPFC");
			
			resultado = pstmt.executeQuery();
			
			while (resultado.next()){
		
			    Alumno alumno=new Alumno();
			    alumno.setIdUsuario(resultado.getInt("idUsuario"));
			    alumno.setDni(resultado.getString("dni"));
			    alumno.setNombre(resultado.getString("nombre"));
			    alumno.setApellidos(resultado.getString("apellidos"));
			    
			    TipoPfc tipoPFC=new TipoPfc();
			    tipoPFC.setIdTipoPfc(resultado.getInt("idTipoPFC"));
			    tipoPFC.setDescripcion(resultado.getString("tipoPFC"));
			    
			    
			    Propuesta propuesta=new Propuesta();
			    propuesta.setIdPropuesta(resultado.getInt("idPropuesta"));
			    propuesta.setTitulo(resultado.getString("titulo"));
			    propuesta.setAnoAcademico(resultado.getInt("anoAcademico"));
			    propuesta.setTipoPfc(tipoPFC);
			        
			    //Obtenemos el estado en que se encuentra la solicitud
			    EstadosSolicitud estado=new EstadosSolicitud();
			    estado.setIdEstado(resultado.getInt("idEstado"));
			    estado.setDescripcion(resultado.getString("estado"));
			    
			    			    
			    Solicitud solicitud=new Solicitud(resultado.getInt("idSolicitud"),
			    								  alumno,propuesta,estado,resultado.getString("urlDocumento"));
				
			    //A�adimos la solicitud a la lista
			     listaSolicitudes.add(solicitud);
			}			
		}catch(SQLException e){
			log.error(e);
		} finally {
			try {
				resultado.close();
				resultado = null;
			} catch (Exception e) { }
			
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		
		ConnectionFactory.release(conn);
		return listaSolicitudes;
		
	}

	/**
	 * @param idUsuario Id del alumno del que comprobar si tiene SolicitudActiva
	 * 
	 * @result devuelve una lista de solicitudes activas (en caso de que las haya)
	 */
	
	public boolean isAlumnoConSolicitudActiva(int idUsuario) {

		Connection conn = ConnectionFactory.getConnection();
		PreparedStatement pstmt = null;
		ResultSet resultado = null;
		boolean tieneSolicitudes = false;
		
		try{
			
			String consulta = "SELECT u.idUsuario FROM usuarios AS u " + 
				"INNER JOIN solicitudes AS s ON u.idUsuario=s.idAlumno " + 
				"WHERE s.idEstado IN(1,2) AND u.idUsuario=?";
			
			pstmt = conn.prepareStatement(consulta);
			pstmt.setInt(1, idUsuario);
			resultado = pstmt.executeQuery();
			
			if (resultado.next()){
				tieneSolicitudes = true;
			}			
		}catch(SQLException e){

		} finally {
			try {
				resultado.close();
				resultado = null;
			} catch (Exception e) { }
			
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		
		ConnectionFactory.release(conn);
		return tieneSolicitudes;
	}
	
	
	public List getSolicitudesPendientes(){
		
		Connection conn = ConnectionFactory.getConnection();
		PreparedStatement pstmt = null;
		ResultSet resultado = null;
		Solicitud solicitud = null;
		int i=0;
		ArrayList<Solicitud> listaSolicitudes=new ArrayList<Solicitud>();
		try {
			
			pstmt = conn.prepareStatement("select sol.idRelacion as idSolicitud, us.idUsuario, us.dni, us.nombre, us.apellidos, sol.idPropuesta,"+
					"sol.urlDocumento,sol.idEstado, est.descripcion as estado, pro.idProfesor, pro.titulo, pro.anoAcademico,pro.idTipoPFC,pro.descripcion, pfc.descripcion as tipoPFC, "+
					"usp.idUsuario as idProfesor, usp.nombre as nombreProfesor, usp.apellidos as apellidosProfesor "+
					"from   usuarios us, solicitudes sol, propuestas pro, estados_solicitud est, tipo_pfc pfc, usuarios usp "+
					"where sol.idEstado= 1 "+ 
					"and usp.idUsuario=pro.idProfesor " +
					"and us.idUsuario=sol.idAlumno "+
					"and sol.idPropuesta=pro.idPropuesta "+					
					"and est.idEstado=sol.idEstado "+
					"and pfc.idTipoPFC=pro.idTipoPFC;");
			
			resultado = pstmt.executeQuery();	
			
			while (resultado.next()){
				 i++;
				 Alumno alumno=new Alumno();
				 alumno.setIdUsuario(resultado.getInt("idUsuario"));
				 alumno.setNombre(resultado.getString("nombre"));
				 alumno.setApellidos(resultado.getString("apellidos"));
				 alumno.setDni(resultado.getString("dni"));
				    
				 TipoPfc tipoPFC=new TipoPfc();
				 tipoPFC.setIdTipoPfc(resultado.getInt("idTipoPFC"));
				 tipoPFC.setDescripcion(resultado.getString("tipoPFC"));
				    
				 Profesor profesor=new Profesor();
				 
				 profesor.setIdUsuario(resultado.getInt("idProfesor"));
				 profesor.setNombre(resultado.getString("nombreProfesor"));
				 profesor.setApellidos(resultado.getString("apellidosProfesor"));
				 
				 Propuesta propuesta=new Propuesta();
				 propuesta.setIdPropuesta(resultado.getInt("idPropuesta"));
				 propuesta.setTitulo(resultado.getString("titulo"));
				 propuesta.setTipoPfc(tipoPFC);
				 propuesta.setAnoAcademico(resultado.getInt("anoAcademico"));
				 propuesta.setDescripcion(resultado.getString("descripcion"));
				 propuesta.setProfesor(profesor);
				        
				 //Obtenemos el estado en que se encuentra la solicitud
				 EstadosSolicitud estado=new EstadosSolicitud();
				 estado.setIdEstado(resultado.getInt("idEstado"));
				 estado.setDescripcion(resultado.getString("estado"));
				    
				 solicitud=new Solicitud(resultado.getInt("idSolicitud"),alumno,propuesta,estado,resultado.getString("urlDocumento"));
				 listaSolicitudes.add(solicitud);
				 
			}
		} catch (SQLException e) {
			solicitud = null;			
		} finally {
			try {
				resultado.close();
				resultado = null;
			} catch (Exception e) { }
			
			try {
				pstmt.close();
				pstmt = null; 
			} catch (Exception e) { }
		}
		
		ConnectionFactory.release(conn);
		if (i==0){
			listaSolicitudes=null;
		}
		return listaSolicitudes;
	}
	
	
		

}
